home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / ams__l~1.zoo / src / fastcoun.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-25  |  4.8 KB  |  267 lines

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is part of the Atari Machine Specific Library,
  4. //  and is Copyright 1992 by Warwick W. Allison.
  5. //
  6. //  You are free to copy and modify these sources, provided you acknowledge
  7. //  the origin by retaining this notice, and adhere to the conditions
  8. //  described in the file COPYING.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include "FastCounter.h"
  13. #include "DoubleBuffer.h"
  14.  
  15. CounterFont::CounterFont(short Height) :
  16.     height(Height)
  17. {
  18.  
  19.     for (shifts=0; 1<<shifts < Height; shifts++);
  20.  
  21.     Data=new short[111<<shifts];
  22. }
  23.  
  24. void CounterFont::GetImages(Screen& S,short x,short y)
  25. {
  26.     short WPL=S.Rez().BytesPerLine()/2;
  27.     short BP=S.Rez().BitPlanes();
  28.     short *From=(short*)S.Location()+((x>>4)*BP)+y*WPL;
  29.     int n;
  30.  
  31.     short *Blank=Data+(110<<shifts);
  32.     for (int h=0; h<height; h++) {
  33.         Blank[h]=From[h*WPL-BP];
  34.     }
  35.  
  36.     for (n=0; n<=9; n++) {
  37.         short *D=Data+((n+100)<<shifts);
  38.         for (int h=0; h<height; h++) {
  39.             D[h]=*(From+WPL*h);
  40.             if (!(n&1)) D[h]>>=8;
  41.             D[h]&=0xFF;
  42.             D[h]|=Blank[h]<<8;
  43.         }
  44.         if (n&1) From+=BP;
  45.     }
  46.  
  47.     for (n=0; n<=99; n++) {
  48.         short *D=Data+(n<<shifts);
  49.         short *S1=Data+((n/10+100)<<shifts);
  50.         short *S2=Data+((n%10+100)<<shifts);
  51.         for (int h=0; h<height; h++) {
  52.             D[h]=((S1[h]&0xff)<<8)|(S2[h]&0xff);
  53.         }
  54.     }
  55. }
  56.  
  57. void CounterFont::Draw(short n,long Offset)
  58. {
  59.     short *At=(short*)Pages->Location()+Offset;
  60.     short WPL=Pages->Current().Rez().BytesPerLine()/2;
  61.     short *D=Data+(n<<shifts);
  62.     for (int h=0; h<height; h++) {
  63.         *At=*D;
  64.         D++;
  65.         At+=WPL;
  66.     }
  67. }
  68.  
  69. FastCounter::FastCounter(CounterFont* F,int x,int y,unsigned v=0,short digits=6,short plane=0) :
  70.     Font(F),
  71.     LeadingZeroes(FALSE),
  72.     Size((digits>>1)+(digits&1)),
  73.     Digit(new unsigned short[Size]),
  74.     Offset(((x>>4)*Pages->Current().Rez().BitPlanes())+y*(Pages->Current().Rez().BytesPerLine()/2)+(Size-1)*Pages->Current().Rez().BitPlanes()+plane)
  75. {
  76.     Changed[0]=Size;
  77.     Changed[1]=Size;
  78.     Set(v);
  79. }
  80.  
  81. FastCounter::~FastCounter()
  82. {
  83.     delete Digit;
  84. }
  85.  
  86. void FastCounter::Draw()
  87. {
  88.     long O=Offset;
  89.     short top=Changed[Pages->Pulse];
  90.     short BP=Pages->Current().Rez().BitPlanes();
  91.  
  92.     for (int d=0; d<top; d++) {
  93.         Font->Draw(Digit[d],O);
  94.         O-=BP;
  95.     }
  96.     Changed[Pages->Pulse]=0;
  97. }
  98.  
  99. void FastCounter::Add(short Carry)
  100. {
  101.     unsigned short *D=Digit;
  102.  
  103.     int Ch=0;
  104.     if (Carry > 0) {
  105.         while (Carry && Ch<Size) {
  106.             short C;
  107.             if (LeadingZeroes || *D<100) {
  108.                 C=Carry+*D;
  109.             } else {
  110.                 if (*D==110)
  111.                     C=Carry;
  112.                 else
  113.                     C=Carry+*D-100;
  114.             }
  115.             Carry=0;
  116.             while (C>=1000) {
  117.                 C-=1000;
  118.                 Carry+=10;
  119.             }
  120.             while (C>=100) {
  121.                 C-=100;
  122.                 Carry++;
  123.             }
  124.             *D++=C;
  125.             Ch++;
  126.         }
  127.     } else {
  128.         // Carry <= 0
  129.         while (Carry && Ch<Size) {
  130.             short C;
  131.             if (LeadingZeroes || *D<100) {
  132.                 C=Carry+*D;
  133.             } else {
  134.                 if (*D==110)
  135.                     C=Carry;
  136.                 else
  137.                     C=Carry+*D-100;
  138.             }
  139.             Carry=0;
  140.             while (C<=-1000) {
  141.                 C+=1000;
  142.                 Carry-=10;
  143.             }
  144.             while (C<0) {
  145.                 C+=100;
  146.                 Carry--;
  147.             }
  148.             *D++=C;
  149.             Ch++;
  150.         }
  151.     }
  152.  
  153.     Changed[0]=Changed[0] >? Ch >? Changed[1];
  154.     Changed[1]=Changed[0];
  155.  
  156.     // At this point, *D is the first unchanged bigit,
  157.     // so if it is "  ", then some of the changed bigits
  158.     // may need to have leading zeroes removed.
  159.  
  160.     if (!LeadingZeroes && (Ch==Size || *D==110)) {
  161.         while (Ch>0 && *--D<10) {
  162.             if (*D || Ch==1) {
  163.                 *D+=100;
  164.                 Ch=0;
  165.             } else {
  166.                 *D=110;
  167.             }
  168.             Ch--;
  169.         }
  170.     }
  171. }
  172.  
  173. void FastCounter::ZeroSuppression(bool on=TRUE)
  174. {
  175.     LeadingZeroes=!on;
  176.     Changed[0]=Size;
  177.     Changed[1]=Size;
  178.  
  179.     unsigned short *D=&Digit[Size-1];
  180.  
  181.     if (!LeadingZeroes) {
  182.         int Ch=Size;
  183.         while (Ch>0 && *--D<10) {
  184.             if (*D || Ch==1) {
  185.                 *D+=100;
  186.                 Ch=0;
  187.             } else {
  188.                 *D=110;
  189.             }
  190.             Ch--;
  191.         }
  192.     } else {
  193.         int Ch=Size;
  194.         while (Ch>0 && *--D>99) {
  195.             if (*D<110) {
  196.                 *D-=100;
  197.                 Ch=0;
  198.             } else {
  199.                 *D=0;
  200.             }
  201.             Ch--;
  202.         }
  203.     }
  204. }
  205.  
  206. void FastCounter::Set(unsigned Carry)
  207. {
  208.     unsigned short *D=Digit;
  209.  
  210.     for (int d=0; d<Size; d++) {
  211.         if (!LeadingZeroes && Carry<10) {
  212.             if (Carry || !d) {
  213.                 *D++=Carry%10+100;
  214.                 Carry=0;
  215.             } else {
  216.                 *D++=110;
  217.             }
  218.         } else {
  219.             *D++=Carry%100;
  220.             Carry/=100;
  221.         }
  222.     }
  223.     Changed[0]=Size;
  224.     Changed[1]=Size;
  225. }
  226.  
  227. void FastCounter::MoveTo(short x,short y,short plane=0)
  228. {
  229.     Offset=((x>>4)*Pages->Current().Rez().BitPlanes())+y*(Pages->Current().Rez().BytesPerLine()/2)+plane;
  230.     Changed[0]=Size;
  231.     Changed[1]=Size;
  232. }
  233.  
  234. FastCounter::operator int()
  235. {
  236.     int result=0;
  237.     for (int d=Size; d>=0; d--) {
  238.         if (LeadingZeroes || Digit[d]<100) {
  239.             result=result*100+Digit[d];
  240.         } else {
  241.             if (Digit[d]==110) {    
  242.                 result=result*100;
  243.             } else {
  244.                 result=result*100+(Digit[d]-100);
  245.             }
  246.         }
  247.     }
  248.     return result;
  249. }
  250.  
  251. FastCounter::operator double()
  252. {
  253.     double result=0.0;
  254.     for (int d=Size; d>=0; d--) {
  255.         if (LeadingZeroes || Digit[d]<100) {
  256.             result=result*100.0+(double)Digit[d];
  257.         } else {
  258.             if (Digit[d]==110) {    
  259.                 result=result*100.0;
  260.             } else {
  261.                 result=result*100.0+(double)(Digit[d]-100);
  262.             }
  263.         }
  264.     }
  265.     return result;
  266. }
  267.